header <- function (.type = NULL) {
    cat("==========\n\n")
    cat(paste("Running ", .type, '\n', sep = ""))
    return(NULL)
}

footer <- function() {cat("==========\n\n")}

estimator <- function (.rc = NULL,
                       .type = NULL,
                       .polarity = NULL
                       ) {
    require("pscl")
    require("wnominate")
    require("oc")
    require("emIRT")

    cidx <- which(.rc$legis.data$icpsrLegis == .polarity[1])
    lidx <- which(.rc$legis.data$icpsrLegis == .polarity[2])

    header(.type)

    switch(.type,
           "ideal" = {
               out <- ideal(object = .rc,
                            d = 1,
                            maxiter = 120e3,
                            thin = 100,
                            burnin = 20e3,
                            ## maxiter = 120,
                            ## thin = 1,
                            ## burnin = 20,
                            impute = FALSE,
                            normalize = TRUE,
                            store.item = TRUE,
                            verbose = FALSE
                            )
               predprob <- matrix(NA, ncol = ncol(.rc$votes), nrow = nrow(.rc$votes))
               pred <- predprob
               correct <- predprob
               x1 <- cbind(out$xbar, -1)
               b <- out$betabar
               mu <- tcrossprod(x1, b)
               predprob <- pnorm(mu)
               pred <- predprob >= .5
               votes <- convertCodes(.rc)
               correct <- votes == pred
               correct[is.na(votes)] <- NA
               out$csr <- mean(correct, na.rm = TRUE)
               out$beta <- NULL
           },
           "ideal2" = {
               out <- ideal(object = .rc,
                            d = 1,
                            maxiter = 1e6 + 50e3,
                            thin = 500,
                            burnin = 50e3,
                            ## maxiter = 120,
                            ## thin = 1,
                            ## burnin = 20,
                            impute = TRUE,
                            normalize = TRUE,
                            store.item = TRUE,
                            verbose = FALSE
                            )
               predprob <- matrix(NA, ncol = ncol(.rc$votes), nrow = nrow(.rc$votes))
               pred <- predprob
               correct <- predprob
               x1 <- cbind(out$xbar, -1)
               b <- out$betabar
               mu <- tcrossprod(x1, b)
               predprob <- pnorm(mu)
               pred <- predprob >= .5
               votes <- convertCodes(.rc)
               correct <- votes == pred
               correct[is.na(votes)] <- NA
               out$csr <- mean(correct, na.rm = TRUE)
               out$beta <- NULL
           },
           "wnominate" = {
               out <- wnominate(.rc,
                                dims = 1,
                                trials = 1,
                                verbose = TRUE,
                                polarity = cidx
                                )
           },
           "oc" = {
               out <- oc(.rc,
                         dims = 1,
                         polarity = cidx,
                         verbose = TRUE
                         )
           },
           "fastest" = {
               .rc <- dropRollCall(.rc,
                                   dropList = list(codes = "notInLegis", lop = 0)
                                   )
               .rc <- convertRC(.rc)
               .priors <- makePriors(.rc$n, .rc$m, 1)
               .starts <- getStarts(.rc$n, .rc$m, 1)
               out <- binIRT(.rc,
                             .starts = .starts,
                             .priors = .priors,
                             .control = list(threads = 1,
                             thresh = 1e-6,
                             asEM = TRUE
                             )
                             )
           },
           "fastestBS" = {
               .rc <- dropRollCall(.rc,
                                   dropList = list(codes = "notInLegis", lop = 0)
                                   )
               .rc <- convertRC(.rc)
               .priors <- makePriors(.rc$n, .rc$m, 1)
               .starts <- getStarts(.rc$n, .rc$m, 1)
               out <- binIRT(.rc,
                             .starts = .starts,
                             .priors = .priors,
                             .control = list(threads = 1,
                             thresh = 1e-2,
                             asEM = TRUE
                             )
                             )
               loutbs <- runPBS(.output = out,
                                .priors = .priors,
                                .bsiter = 100,
                                .asEM = TRUE,
                                .thresh = 1e-2
                                )
           },
           "fastestLOW" = {
               .rc <- dropRollCall(.rc,
                                   dropList = list(codes = "notInLegis", lop = 0)
                                   )
               .rc <- convertRC(.rc)
               .priors <- makePriors(.rc$n, .rc$m, 1)
               .starts <- getStarts(.rc$n, .rc$m, 1)
               out <- binIRT(.rc,
                             .starts = .starts,
                             .priors = .priors,
                             .control = list(threads = 1,
                             thresh = 1e-2,
                             asEM = TRUE
                             )
                             )
           },
           "fastestMP" = {
               .rc <- dropRollCall(.rc,
                                   dropList = list(codes = "notInLegis", lop = 0)
                                   )
               .rc <- convertRC(.rc)
               .priors <- makePriors(.rc$n, .rc$m, 1)
               .starts <- getStarts(.rc$n, .rc$m, 1)
               out <- binIRT(.rc,
                             .starts = .starts,
                             .priors = .priors,
                             .control = list(threads = 8,
                             thresh = 1e-6,
                             asEM = TRUE
                             )
                             )
           },
       {
           stop("no known method")
       }
           )

    footer()

    ret <- list()
    ## ret$rc <- .rc
    ret$type <- .type
    ret$output <- out
    return(invisible(ret))
}
